\documentclass[a4paper,10pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}
\usepackage[paper=a4paper,left=23mm,right=23mm,top=30mm,bottom=15mm]{geometry} 
\usepackage{bera}
\usepackage{graphicx}
\usepackage{listings}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{caption}
\usepackage{subfigure}
\usepackage{fancyhdr}

\pagestyle{fancy}
%opening
\title{Computer Grafik 3: Aufgabe 4, Die Grundrechenarten}
\author{Michael Antemann  (1061753)}

\begin{document}
\shorthandoff{"}

\begin{titlepage}
%\begin{center}


\date{\today}

\vspace{10cm}
\maketitle
\begin{figure}[htbp]
\centering
  \includegraphics[width=400pt,height=300pt]{deckblatt_img.jpg}  
\caption[Deckblatt]{Dock Minus Desert Plus Dock Minus Oryx Antelope}
  \label{fig:Deckblatt}
\end{figure}
\thispagestyle{empty}
\begin{abstract}
Das Programm ergmöglicht es mehrere Bilder zum Arbeiten zu öffnen. Auf die Bilder können dann die 4 Grundrechenarten angewandt werden. 
Zudem besteht die Möglichkeit ein einzelnes Bild mit einem Konstanten Faktor mit den Grundrechenarten zu Verrechnen. Als auch ein Bild mit einem anderen Bild zu verrechnen.
Die erzeugten Ergebnisse tauchen in der Liste auf, und können ebenfalls weiter verarbeitet werden. Eine Funktion zum speichern von erzeugten Bildern ist ebenfalls integriert.
\end{abstract}
\end{titlepage}

\newpage
\tableofcontents  % Inhaltsverzeichnis
\newpage


\section{Einleitung}
Im Rahmen der Aufgabe habe ich ein Java Programm geschrieben welches die Möglichkeit bietet, ein Bild mit einer Konstante oder einem anderen Bild zu verrechnen.
Als Rechenoperation, stehen dabei die vier Grundrechenarten Addieren, Subtrahieren, Multiplizieren und Dividieren zur Verfügung.
Neu erzeugte Bilder können direkt über das Programm auf der Festplatte gespeichert werden.
Eine genauere Anleitung steht im nächsten Abschnitt oder kann im Programm über den Menüeintrag "Hilfe"  abgerufen werden.

\section{Technische Umsetzung}
\subsection{Das Programm}
Die Anwendung ist in Java geschrieben und basiert auf dem MVC Prinzip. Die grafische Komponente wurde zum Großteil mit hilfe eines GUI Design Editors[\ref{lit:Jigloo}] entwickelt. Andere verwendete API's sind in den folgenden Abschnitten beschrieben. 

Das Programm sollte wie in den folgenden Zeilen beschrieben benutzt werden.
Über Datei-> Öffnen können mehrere Bilder geöffnet werden, auf die dann über die Tabelle oben links zugegriffen werden kann. Oben in der Mitte wird in der Regel das akutell ausgewählte Bild dargestellt, nach einer Berechnung sieht man hier auch das neu berechnete Bild. Ist ein Bild gewählt, kann man eine Operation z.B. Addieren auswählen. Das Bild ist nun als Operand1 erfasst. Möchte man das Bild nun mit einem anderen Addieren wählt man aus der Liste nun ein zweites Bild aus und klickt auf "Berechnen".
Das zweite Bild wird nun als Operator2 erfasst und das Ergebnis wird in die Liste eingetragen und oben in der Mitte dargestellt.
Alternativ kann man auch über die beiden Radio Button auswählen Operator 1 mit einem Konstanten Faktor zu verrechnen. Wählt man diese Option aus, wird das Textfeld dadrunter aktiv und man kann eine Gleitkommazahl eintragen. Ob die Eingabe sinnvoll ist, wird allerdings nicht vom Programm überprüft.
Mit den Button oben rechts "Bild speichern" und "Bild schließen" kann man das aktuell ausgewählte Bild speichern oder schließen. 
\subsection{Java JAI}
Die gesamte Bildverarbeitung stützt sich auf der Java Advanced Imaging API "JAI" und ImageIO von Sun[\ref{lit:JAI}]. JAI bietet einen sehr umfangreichen Zugriff auf und Bearbeitungsmöglichkeiten auf Bild-Objekte.
Zum Speichern der Bilder auf der Festplatte wird dagegen ImageIO verwendet.  ImageIO ermöglicht nämlich das speichern eines Bildes mittels eines einfachen ImageIO.write() Aufrufes.

Für diese Anwendung, reicht es die Bilder als "PlanarImage" einzulesen. Dies ist die standard Klasse in der die 2d Bilder vorgehalten werden. Ein aufruf zum Laden eines Bildes sieht dann z.B. so aus:
\lstset{language=Java}
\begin{lstlisting}
 PlanarImage image = JAI.create("fileload", fileObject);
\end{lstlisting}


Die konkreten Daten des Bildes sind nun geladen. Mittels JAI können diese auch direkt weiter verarbeitet werden. Man kann sich ein Raster erstellen das dann bearbeitet werden kann, oder man nutzt die create() methode von JAI die unten beschrieben ist.
Zur grafischen Darstellung eines geladenen PlanarImage Objektes im GUI, enthält die JAI-API die Klasse "DisplayJAI". Möchte man nun das geladene Bild in einem Java Swing Frame darstellen kann man die "set(PlanarImage image)" methode von DisplayJAI nutzen.
Die folgende Codezeile sorgt für die Darstellung eines Bildes.

 
\lstset{language=Java}
\begin{lstlisting}
	displayJAIObject.set(image);
\end{lstlisting}


Da DisplayJAI ein "null Layout" nutzt sollte man das DisplayJAI objekt in eine Scrollpane oder ähnliches einbetten, wie in der Applikation geschehen.

Für eigentliche Verarbeitung der Bilder nutzt die Anwendung die create() Methode von JAI. Dieser Methode übergibt man per String eine Operation z.B. "ADD" oder "Multiply". Als zweiten Parameter erwaretet die Methode einen ParameterBlock, dieser enthält die Objekte mit denen oder auf die, die Operation durchgeführt wird. Als Beispiel folgt der Sourcecode einer solchen Operation. In diesem Fall wird von einem Bild ein konstanter Faktor abgezogen.
\newpage 
\lstset{language=Java}
\begin{lstlisting}
	PlanarImage sub(Image operand1, double[] faktor) {
		ParameterBlock pb = new ParameterBlock();
		pb.addSource(operand1.getContent());
		pb.add(faktor);
		PlanarImage result = JAI.create("SubtractConst", pb, null);
		return result;
	}
\end{lstlisting}

Das Double Array "faktor" stellt in diesem Beispiel eine Konstante dar, die für jeden Farbkanal einen Wert enthält der von jedem Farbwert des jewiligen Kanals vom Bild "operand1" abgezogen wird. 
Der create() Aufruf gibt dann ein fertig gerendertes Bild zurück. 

Die create() Methode geht dabei im Falle 2 er Bilder, beide Bilder Pixel für Pixel durch. Dabei wird das entsprechende Pixel des einen Bildes mit dem Pixel des anderen Bildes verrechnet. Dies Geschieht bei allen 4 Rechenarten auf gleiche Weise. Wird ein Bild mit einer Konstante verarbeitet, so wird jedes Pixel eines Bildes mit der Konstante verarbeitet. Das ganze geschieht für jeden Farbkanal eines Bildes je einmal. 
Kommt es bei der Verarbeitung dazu das ein Bild mehr Farbkanäle hat als das andere, oder die Bilder nicht gleich groß sind, so "einigt" sich die Create methode auf den kleinsten gemeinsamen Nenner. Das heißt das Pixel die kein gegenstück im anderne Bild haben weg geschnitten werden. Ist ein Farbkanal zu wenig vorhanden so wir dieser mit "0" Werten verarbeitet.

Kommt es bei der Verarbeitung dazu das ein theoretischer Farbwert das Maximum oder Minimum einer Farb- bzw Datentypdefinition über- oder unterschreitet, so wird er auf das Maximum oder Minimum gesetzt. Bei der Division gibt es zusätlich noch den sonderfall das durch Null geteilt wird, dann wird der Wert auf den maximal wert gesetzt. Steht die 0 im Zähler, so wird der Wert auf 0 gesetzt. So entstehen keine undefinierten Pixel.

Die vorgehensweise von create ist ausführlich im JAI-API Pdf[\ref{lit:JAIDoku}] beschreiben.

\begin{figure}[htbp]
\centering
  \includegraphics[width=400pt,height=300pt]{Applikation.png}  
\caption[Das Programm]{Das Programm}
  \label{fig:prog}
\end{figure}

\section{Implementierte Operationen}
\subsection{Addition}
Bei der Addition werden die jeweiligen Farbwerte mit einander Addiert, das führt dazu das früher oder später alles Weiß wird. Wenn man nun ein Bild mit einen mittleren oder niedrigen konstanten Wert  addiert eignet sich dies bedingt zum Aufhellen. Beim Addieren von zwei verschiedenen Bildern, kann man günstig nette effekte erziehlen, siehe Abb.  [\ref{fig:dad}] welches aus zwei Bildern besteht, Abb.  [\ref{fig:dock}] und Abb. [\ref{fig:Desert}] welche addiert wurden. Dabei sollte man drauf achten das die farblichen Schwerpunkte der unterschiedlichen Bilder möglichst aus unterschiedlichen Farbkanälen bestehen, damit diese sich nicht all zu sehr überlagern. Die Reihenfolge der Operanden spielt bei der Addition von 2 Bildern keine Rolle, d.h. $a + b = b + a = c$

\subsection{Subtraktion}
Durch Subtraktion lassen sich ähnliche Bilder erzeugen, wie bei der Addition. Praktisch kann man es als Umkehrfunktion betrachten allerdings gilt hierbei  $a + b  \neq b + a $ siehe dazu [\ref{fig:demdo}] und [\ref{fig:domde}] . Das Bild wird hierbei immer dunkler.

Addition und Subtraktion werden in der Praxis hauptsächlich zur Rauschminderung eingesetzt.
\subsection{Multiplikation}
Bei der Multiplikation werden die Farben extremer, d.h. helle Bilder werden meist ausschlieslisch weiss Abb. [\ref{fig:desertmulturtle}]  . Bei dunkleren Bildern hier, eine verdunkelte Wüste Abb. [\ref{fig:darkd}] welche dann mit sich selbst Multipliziert wurde, Abb. [\ref{fig:darkdmdd}]. 
\subsection{Division}
Durch Divisionen entsteht oft ein Bild mit vielen schwarzes Zonen. Allerdings lassen sich auch ähnliche ergebnisse wie bei der Multiplikation erzielen siehe: Abb.  [\ref{fig:desertdivturtle}] .
\newpage
\section{Ergebnisse}
\begin{figure}[htbp]
\centering
  \includegraphics[width=400pt,height=300pt]{DesertLandscape.jpg}  
\caption[Desert]{Desert}
  \label{fig:Desert}
\end{figure}

\begin{figure}[htbp]
\centering
  \includegraphics[width=400pt,height=300pt]{Dock.jpg}  
\caption[Dock]{Dockt}
  \label{fig:dock}
\end{figure}

\begin{figure}[htbp]
\centering
  \includegraphics[width=400pt,height=300pt]{OryxAntelope.jpg}  
\caption[Oryx Antelope]{Oryx Antelope}
  \label{fig:Oryx}
\end{figure}

\begin{figure}[htbp]
\centering
  \includegraphics[width=400pt,height=300pt]{DockAddierenDesertLandscape.jpg}  
\caption[Dock Plus Desert]{Dock Addiert mit Desert}
  \label{fig:dad}
\end{figure}

\begin{figure}[htbp]
\centering
  \includegraphics[width=400pt,height=300pt]{dockminusdesert.jpg}  
\caption[Dock Minus Desert Landscape]{Dock Minus Desert}
  \label{fig:domde}
\end{figure}

\begin{figure}[htbp]
\centering
  \includegraphics[width=400pt,height=300pt]{dersertminusdock.jpg}  
\caption[Desert Minus Dock]{Desert Minus Dock}
  \label{fig:demdo}
\end{figure}

\begin{figure}[htbp]
\centering
  \includegraphics[width=400pt,height=300pt]{Garden.jpg}  
\caption[Garten, Blumen]{Blumen}
  \label{fig:garden}
\end{figure}

\begin{figure}[htbp]
\centering
  \includegraphics[width=400pt,height=300pt]{darkdesert.png}  
\caption[Verdunkelte Wüste (Desert Minus 200)]{Dunkle Wüste  (Desert Minus 200)}
  \label{fig:darkd}
\end{figure}

\begin{figure}[htbp]
\centering
  \includegraphics[width=400pt,height=300pt]{darkdesertmulti.png}  
\caption[Dunkle Wüste mit sich selber Multipliziert]{Verdunkelte Wüste mit sich selbst Multipliziert}
  \label{fig:darkdmdd}
\end{figure}

\begin{figure}[htbp]
\centering
  \includegraphics[width=400pt,height=300pt]{desertmultiturtle.jpg}  
\caption[Wüste Multipliziert mit See Schildkröte]{Wüste Multipliziert mit See Schildkröte}
  \label{fig:desertmulturtle}
\end{figure}

\begin{figure}[htbp]
\centering
  \includegraphics[width=400pt,height=300pt]{desertdivturtle.jpg}  
\caption[Wüste Division mit See Schildkröte]{Wüste Division mit See Schildkröte}
  \label{fig:desertdivturtle}
\end{figure}


\newpage
\section{Anhang}
\begin{thebibliography}{99}
\bibitem{Jigloo}\label{lit:Jigloo}
Jigloo SWT/Swing GUI Builder for Eclipse and WebSphere 
http://www.cloudgarden.com/jigloo/

\bibitem{JAI}\label{lit:JAI}
Java Advanced Imaging API \\
JAI Hauptseite - http://java.sun.com/javase/technologies/desktop/media/jai/ \\
Image IO - https://jai-imageio.dev.java.net/ \\

\bibitem{JAI-Api Pdf}\label{lit:JAIDoku}
Komplette JAI Dokumentation - http://dlc.sun.com/pdf/806-5413-10/806-5413-10.pdf \\

\end{thebibliography}


\listoffigures
\newpage
\subsection{Sourcecode}
Folgend ist nur der Sourcecode der zum erstellen der Bilder benutzt wird. Auf das Listen der Grafischen Ausgabe habe ich an dieser stelle verzichtet. 
Die Java Dateien liegen dem "JAR" Bei.

\begin{lstlisting}
package de.fhhannover.inform.semester5.computergrafik3.praxisteil.task;

/*
 * Author: 		Michael Antemann (1061753)
 * Date:		08.12.09
 * Description: Bildverarbeitung mit JAI, ermoeglicht die 4 Grundrechenarten. 
 * 
 *
 */
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import java.awt.image.renderable.ParameterBlock;

public class PictureProcessing {
	// Definierte Strings geben die Operationen vor, zum einfacheren
	// vergelichen.
	final static String add = "Addieren";
	final static String mul = "Multiplizieren";
	final static String div = "Dividieren";
	final static String sub = "Subtrahieren";
	final static String pic = "Bild";
	final static String fac = "Faktor";

	// Calculate wertet die Strings aus und entscheided welche Methode
	// ausgefuehrt wird.
	Image calculate(String opMode, String opcode, Image operand1,
			Image operand2, double factor) {
		// op2Name existiert um dem Bild einen namen zu geben. Im Falle das mit
		// Faktor gerechnet wird wird die Zahl zum namen hinzugefaegz, Ansonten
		// der name des 2. Bildes.
		String op2Name = "";
		PlanarImage result = null;
		// Es wird ein Bild mit einem anderen verrechnet. Durch ueberladen wird bestimmt welcher Modus letzendlich ausgefuehrt wird.  
		if (opMode.equals(pic)) {
			if (opcode.equals(add)) {
				result = this.add(operand1, operand2);
			} else if (opcode.equals(mul)) {
				result = this.mul(operand1, operand2);
			} else if (opcode.equals(div)) {
				result = this.div(operand1, operand2);
			} else if (opcode.equals(sub)) {
				result = this.sub(operand1, operand2);

			}
			op2Name = operand2.getName();
			
		}
		// Es wird mit einem Faktor gerechnet.
		else if (opMode.equals(fac)) {
			double[] faktor = new double[3];
			faktor[0] = factor;
			faktor[1] = factor;
			faktor[2] = factor;
			if (opcode.equals(add)) {
				result = this.add(operand1, faktor);
			} else if (opcode.equals(mul)) {
				result = this.mul(operand1, faktor);
			} else if (opcode.equals(div)) {
				result = this.div(operand1, faktor);
			} else if (opcode.equals(sub)) {
				result = this.sub(operand1, faktor);
			}
			op2Name = Double.toString(factor);
		}
		// In meiner Image Klasse wird nun das Bild mit allen Infos erstellt.
		if (result != null) {
			Image img = new Image(result, operand1.getName() + " " + opcode
					+ " " + op2Name);
			return img;
		} else {
			return null;
		}
	}

	//Die folgenden Methoden fuehren alle JAI Operationen aus.
	//Sie sind alle aehnlich und deswegen nur einmal beschrieben.
	//Im Parameter Block werden die Operanden verankert, die ersten 4 fuer Bild mit Bild
	//Die restlichen 4 mit Bild und Konstante.
	//Das Ergebnis wird zurueck gereicht.
	
	PlanarImage add(Image operand1, Image operand2) {
		ParameterBlock pb = new ParameterBlock();
		pb.addSource(operand1.getContent());
		pb.addSource(operand2.getContent());
		PlanarImage result = JAI.create("ADD", pb, null);
		return result;
	}

	PlanarImage mul(Image operand1, Image operand2) {
		ParameterBlock pb = new ParameterBlock();
		pb.addSource(operand1.getContent());
		pb.addSource(operand2.getContent());
		PlanarImage result = JAI.create("MULTIPLY", pb, null);
		return result;
	}

	PlanarImage sub(Image operand1, Image operand2) {
		ParameterBlock pb = new ParameterBlock();
		pb.addSource(operand1.getContent());
		pb.addSource(operand2.getContent());
		PlanarImage result = JAI.create("SUBTRACT", pb, null);
		return result;
	}

	PlanarImage div(Image operand1, Image operand2) {
		ParameterBlock pb = new ParameterBlock();
		pb.addSource(operand1.getContent());
		pb.addSource(operand2.getContent());
		PlanarImage result = JAI.create("DIVIDE", pb, null);
		return result;
	}

	PlanarImage add(Image operand1, double[] faktor) {
		ParameterBlock pb = new ParameterBlock();
		pb.addSource(operand1.getContent());
		pb.add(faktor);
		PlanarImage result = JAI.create("AddConst", pb, null);
		return result;
	}

	PlanarImage mul(Image operand1, double[] faktor) {
		ParameterBlock pb = new ParameterBlock();
		pb.addSource(operand1.getContent());
		pb.add(faktor);
		PlanarImage result = JAI.create("MultiplyConst", pb, null);
		return result;
	}

	PlanarImage sub(Image operand1, double[] faktor) {
		ParameterBlock pb = new ParameterBlock();
		pb.addSource(operand1.getContent());
		pb.add(faktor);
		PlanarImage result = JAI.create("SubtractConst", pb, null);
		return result;
	}

	PlanarImage div(Image operand1, double[] faktor) {
		ParameterBlock pb = new ParameterBlock();
		pb.addSource(operand1.getContent());
		pb.add(faktor);
		PlanarImage result = JAI.create("DivideByConst", pb, null);
		return result;
	}
}


\end{lstlisting}

\end{document}
